﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Antlr.Runtime;
using Antlr.Runtime.Tree;
using System.IO;
using System.Text.RegularExpressions;

namespace WeakScript
{
    public partial class Form1 : Form
    {
        WGLexer lexer;
        WGParser parser;
        Logic logic;
        CommonTree tree;
        StringWriter stringWriter;
        Executor executor;
        ANTLRStringStream Input;
        CommonTokenStream tokens;
        FunctionManager functionManager;

        Regex _keyWords;
        
        
         

        public void Log(string msg){

            outputTextBox.Text+=msg+'\n';
        }

        public void VLog(string msg)
        {

            infoTextBox.Text += msg + '\n';
        }

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            logic = new Logic();
            logic.Log = Log;
            functionManager = new FunctionManager();
            functionManager.RegistrateFunction("Sin",GetSin); 
        }
                
        void ParseTextbox()
        {
            logic.Clean();
            Input = new ANTLRStringStream('['+codeTextBox.Text+']');
            lexer = new WGLexer(Input);
            tokens = new CommonTokenStream(lexer);
            parser = new WGParser(tokens);
            parser.logic = logic;
            stringWriter = new StringWriter();
            parser.TraceDestination = stringWriter;
           
            parser.rmain();
        }

        private void GetSin(List<WeakVar> args)
        {
            if (args.Count < 2) return;
            
            args[0].floatValue = Math.Sin(args[1].floatValue);
            //args[0].intValue = (long)Math.Sin((double)args[1].intValue);
        }

        private void button1_Click(object sender, EventArgs e)
        {            
            outputTextBox.Text = "";
            infoTextBox.Text = "";
           
            logic.SetCompile(true);

            ParseTextbox();
            
            BuildLog();
           

            string date = DateTime.Now.ToString("yy_MM_dd hh_mm_ss");
            StreamWriter scw = new StreamWriter(date+" code.txt");
            scw.Write(codeTextBox.Text);
            scw.Close();

            executor = new Executor();
            executor.OnFunctionCall += functionManager.ProcessFunction;
            
            executor.ExecuteList(logic.TEXT_CODE);

            ResultLog();
        }

        private void BuildLog()
        {
            if (stringWriter.ToString() != "")
            {
                //richTextBox2.Text = "";
                Log("errors-\n" + stringWriter.ToString());
            }

            outputTextBox.Text += "acode---\n";
            foreach (var item in logic.SHORT_CMD_CODE)
            {
                Log(item);
            }

            var stream = new FileStream("code.bt", System.IO.FileMode.Create);
            BinaryWriter bw = new BinaryWriter(stream);
            foreach (var item in logic.TRIAD_CODE)
            {
                bw.Write(item.com);
                bw.Write(item.arg);
            }

            bw.Close();
            stream.Close();
        }

        private void ResultLog()
        {
            VLog("consts-----");
            foreach (var item in Registr.ConstsNames)
            {
                VLog(item);
            }

            VLog("vars-----");
            for (int i = 0; i < executor.OperationRoom.HeapStack.Count; i++)
            {
                VLog(executor.OperationRoom.HeapStack[i].ToString());
            }

            VLog("stack-----");
            foreach (var item in executor.OperationRoom.WorkStack)
            {
                VLog(item.Name);
            }
        }

        void HighLight()
        {            
            logic.SetCompile(false);
            try
            {
                ParseTextbox();

                int start= codeTextBox.SelectionStart;
                int lgt = codeTextBox.SelectionLength;

                codeTextBox.Select(0, codeTextBox.Text.Length);
                codeTextBox.SelectionColor = Color.Wheat;
                codeTextBox.SelectionBackColor = Color.Empty;

                for (int i = 0, n = tokens.Count; i < n; i++)
                {
                   IToken token = tokens.Get(i);
                   if (token.Channel != WGLexer.DefaultTokenChannel)
                   {
                       codeTextBox.Select(token.StartIndex - 1, token.Text.Length);
                       codeTextBox.SelectionColor = Color.DarkRed;
                   }
                   else
                   {
                       if (token.Type > WGLexer.TAMP && token.Type < WGLexer.TWHILE)
                       {
                           codeTextBox.Select(token.StartIndex - 1, token.Text.Length);
                           codeTextBox.SelectionColor = Color.LightBlue;
                       }
                   }
                } 

                ColorToken("const_int", Color.LightPink);
                ColorToken("const_str", Color.Green);
                ColorToken("var_exp", Color.DarkGray);
                ColorToken("var_set", Color.Gray);
                ColorToken("as_type", Color.Purple, Registr.TypesNames.Contains);
                ColorToken("func_pre_call", Color.Orange, Registr.FunctionsNames.Contains);

                ColorToken("const_null", Color.DarkBlue);
                ColorToken("const_bool", Color.LightBlue);
                ColorToken("const_str", Color.YellowGreen);
                ColorToken("const_char", Color.LawnGreen);
                ColorToken("const_float", Color.Magenta);
                ColorToken("const_int", Color.Navy);

                codeTextBox.SelectionStart = start;
                codeTextBox.SelectionLength = 0;
            }
            catch { }
        }
        delegate bool CheckToken(string tokenText);

        private void ColorToken(string name, Color color, CheckToken checkToken = null)
        {
            if (logic.TokenDescrMap.ContainsKey(name))
                foreach (var token in logic.TokenDescrMap[name])
                {
                    codeTextBox.Select(token.StartIndex - 1, token.Text.Length);
                    codeTextBox.SelectionColor = color;

                    //if (checkToken!=null)
                    //    if(!checkToken(token.Text))
                    //        codeTextBox.SelectionBackColor = Color.DarkSlateGray;
                }
        }

        private void codeTextBox_TextChanged(object sender, EventArgs e)
        {
            Logic.TokenInfo ti = logic.GetLastTokenInfo();
            if (ti.Description == "func_pre_call")
            {
                codeTextBox._listMenu.Items.Clear();
                codeTextBox._listMenu.Items.AddRange(Registr.FunctionsNames.ToArray());
            }
            else if (ti.Description == "pre_type")
            {
                codeTextBox._listMenu.Items.Clear();
                codeTextBox._listMenu.Items.AddRange(Registr.TypesNames.ToArray());
            }
            
        }

        const string borders = "\n\t\r ;(){}\"=+-*&\"'";

        private void codeTextBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (borders.Contains(e.KeyChar))
            {
                HighLight();
            }

        }

        private void codeTextBox_KeyDown(object sender, KeyEventArgs e)
        {
           
        }
    }
}
